package com.rivues.util.log;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.spi.LoggingEvent;
import org.hibernate.exception.ExceptionUtils;

import com.rivues.core.RivuDataContext;
import com.rivues.module.platform.web.model.Log;
import com.rivues.util.RivuTools;
import com.rivues.util.service.cache.CacheHelper;
import com.rivues.util.service.system.DataPersistenceService;

/**
 * 自定义日志处理，将日志信息保存到数据库、Solr或其他 存储库中，异步方式保存日志，不影响性能
 * @author admin
 *
 */
public class R3LogAppender extends AppenderSkeleton {
	private static Logger log = LoggerFactory.getLogger(R3LogAppender.class) ;
	/**
	 * 自定义日志输出，如果调用日志的 类 为 com.rivues开头，则必须 加上 ORGI和  flowid ，如果是启动阶段的日志，则ORGI和FLOWID都是 SYSTEM
	 */
	@Override
	protected void append(LoggingEvent event) {
		if(event!=null){
			String orgi = "SYSTEM" ;
			String flowid = "SYSTEM" ;
			String userid = null;
			String username = null;
			/**
			 * 异步保存日志信息
			 */
			String msg = event.getMessage().toString(); 
			if(event.getLocationInformation()!=null && (event.getLocationInformation().getClassName().startsWith("com.rivues") || event.getLocationInformation().getClassName().startsWith("org.rivu")) && event.getMessage()!=null){
				/**
				 * 
				 */
				Pattern pattern = Pattern.compile("\\[([\\S\\s]*?)\\]") ;
				Matcher matcher = pattern.matcher(msg) ;
				if(matcher.find() && matcher.groupCount()>=1){
					String[] logGroup = matcher.group(1).split("/") ;
					if(logGroup!=null && logGroup.length ==2){
						orgi = logGroup[0] ;
						flowid = logGroup[1] ;
						msg = msg.substring(msg.indexOf(" ")+1) ;
					}else if(logGroup!=null && logGroup.length ==4){
						orgi = logGroup[0] ;
						flowid = logGroup[1] ;
						userid = logGroup[2] ;
						username = logGroup[3] ;
						msg = msg.substring(msg.indexOf(" ")+1) ;
					}
				}
			}
			Log log = new Log(orgi , flowid , msg , event.getLevel().toString() , event.getThreadName());
			log.setUserid(userid) ;
			log.setUsername(username) ;
			log.setClazz(event.getLocationInformation().getClassName()) ;
			log.setMethod(event.getLocationInformation().getMethodName()) ;
			log.setLinenumber(event.getLocationInformation().getLineNumber()) ;
			log.setLogtype(event.getLevel().toString().equals(Level.ERROR.toString()) ? "1" : "0") ;
			log.setFiles(event.getLocationInformation().getFileName()) ;
			log.setStartid(RivuDataContext.getSystemStartID()) ;
			log.setLogtime(String.valueOf(event.timeStamp)) ;
			
			if(event.getThrowableInformation()!=null){
				if(msg==null || msg.length()==0){
					log.setMsg(event.getThrowableInformation().getThrowable().getClass().toString());
				}
				log.setErrorinfo(ExceptionUtils.getFullStackTrace(event.getThrowableInformation().getThrowable())) ;
				
				if(!StringUtils.isBlank(log.getErrorinfo())&&log.getErrorinfo().indexOf("HibernateObjectRetrievalFailureException")>0){
					log.setMemo("数据不存在");//
				}else if(!StringUtils.isBlank(log.getErrorinfo())&&log.getErrorinfo().indexOf("java.lang.NullPointerException")>0){
					log.setMemo("空指针异常");//
				}else if(!StringUtils.isBlank(log.getErrorinfo())&&log.getErrorinfo().indexOf("freemarker.core.InvalidReferenceException")>0){
					log.setMemo("页面异常");//
				}else if(!StringUtils.isBlank(log.getErrorinfo())&&log.getErrorinfo().indexOf("could not execute query")>0){
					log.setMemo("查询执行失败");//
				}else if(!StringUtils.isBlank(log.getErrorinfo())&&log.getErrorinfo().indexOf("ReportException: REPORT_ERR_00001")>0){
					log.setMemo("报表查找失败");//
				}else{
					log.setMemo("R3未知异常");//
				}
				
				String value =  (String) CacheHelper.getDistributedDictionaryCacheBean().getCacheObject("system.config.log.email", orgi) ;
				if(!StringUtils.isBlank(value)){
					try {
						RivuTools.sendMail(value, null, "R3异常信息", new StringBuffer("描述：").append(log.getMemo()).append("<br/><br/><br/>").append(log.getErrorinfo()).toString(), null);
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
			}
			if(event.getLevel().toString().equals(Level.ERROR.toString())){
	//			log.setErrorinfo(event.get) ;
			}
			/**
			 * 加入到异步队列
			 */
			boolean writeLogToDB = true ;
			if (RivuDataContext.isStart()) {
				if(!RivuTools.outputLog(log.getLevels(), log.getOrgi())){
					writeLogToDB = false ;
				}
			}
			if(writeLogToDB){
				DataPersistenceService.persistence(log) ;
			}
		}
	}

	@Override
	public void close() {
		
	}

	@Override
	public boolean requiresLayout() {
		return false;
	}
}
